import 'dart:math';

import 'package:applications/api/applications_api.dart';
import 'package:applications/database/local_db.dart';
import 'package:applications/module/home/bean/application_bean.dart';
import 'package:applications/module/home/po/application_po.dart';
import 'package:applications/state/list_view_state.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

typedef ToastFunction = void Function(String error, {Error? e});

class HomeStateNotifier
    extends StateNotifier<ListViewState<List<ApplicationPo>>> {
  HomeStateNotifier({required this.api})
      : super(const ListViewState.loading()) {
    init();
  }
  final EasyRefreshController _refreshController = EasyRefreshController(
    controlFinishRefresh: true,
    controlFinishLoad: true,
  );

  EasyRefreshController get refreshController => _refreshController;

  final ApplicationsAPI api;

  String get search => _search;

  // 当前页码
  int _page = 0;
  // 每页显示条目
  final int _pageSize = 10;
  // 搜索条件
  String _search = '';

  /// 数据源
  late final datas = Provider.autoDispose<List<ApplicationPo>>((ref) {
    return ref.watch(productModelProvider.notifier)._products;
  });

  // 下载量最多的APP
  List<ApplicationPo> _products = [];

  // 最受欢迎的App
  List<Entry> listTopgrossing = [];

  void init() {
    firstLoadPage();
  }

  Future<void> firstLoadPage() async {
    _page = 0;
    try {
      // 最受歡迎的Apps
      listTopgrossing = await api.topgrossing(limit: 10);

      // 下載量最多的免費App
      final List<Entry> list = await api.topfree();
      List<ApplicationPo> listPo = [];
      for (var i = 0; i < list.length; i++) {
        Entry entry = list[i];
        listPo.add(ApplicationPo.beanToPo(entry, i));
      }
      LocalDb.instance.applicationDao.inserts(listPo);
      if (list.isEmpty && listTopgrossing.isEmpty) {
        state = const ListViewState.empty();
      } else {
        // 取前面十个用于展示(可避免请求数据库的开销,但是map与对象转换也存在开销)
        _products = list
            .getRange(0, min(listPo.length, 10))
            .map((bean) => ApplicationPo.beanToPo(bean, 0))
            .toList();
        // 从数据库中取前十条数据
        // _products = await LocalDb.instance.applicationDao
        //     .queryPages(_pageSize, _page * _pageSize);
        state = ListViewState.ready(_products);
      }
      _refreshController.finishRefresh(IndicatorResult.success);
    } catch (e) {
      state = ListViewState.error(error: e.toString());
    }
  }

  Future<void> refreshData({ToastFunction? fnToast}) async {
    _page = 0;
    try {
      // var response = await api
      //     .topgrossing()
      //     .then((String value) => ApplicationBean.fromJson(jsonDecode(value)));
      // listTopgrossing = response.feed?.entry ?? [];

      listTopgrossing = await api.topgrossing();
      final List<ApplicationPo> list = await _request();
      if (list.isEmpty) {
        state = const ListViewState.empty();
      } else {
        _products = list;
        state = ListViewState.ready(_products);
      }
      _refreshController.finishRefresh(IndicatorResult.success);
    } catch (e) {
      _refreshController.finishRefresh(IndicatorResult.fail);
      if (fnToast != null) {
        fnToast(e.toString());
      }
    }
  }

  Future<void> loadMore({ToastFunction? fnToast}) async {
    if (_search != '') {
      _refreshController.finishLoad(IndicatorResult.noMore);
      return Future.value();
    }
    _page += 1;
    try {
      final List<ApplicationPo> list = await _request();
      if (list.isNotEmpty) {
        _products.addAll(list);
        state = ListViewState.ready(_products);
        _refreshController.finishLoad(IndicatorResult.success);
      }
      // 搜索条件不为空时, 不进行分页查询
      if (_page >= 9) {
        _refreshController.finishLoad(IndicatorResult.noMore);
      }
    } catch (e) {
      _refreshController.finishLoad(IndicatorResult.fail);
      if (fnToast != null) {
        fnToast(e.toString());
      }
    }
  }

  Future<void> queryByName(String search) async {
    _page = 0;
    try {
      _search = search;
      List<ApplicationPo> list = await _request();
      if (list.isEmpty) {
        state = const ListViewState.empty();
      } else {
        _products = list;
        state = ListViewState.ready(_products);
      }
      _refreshController.finishLoad(IndicatorResult.success);
    } catch (e) {
      state = ListViewState.error(error: e.toString());
      _refreshController.finishLoad(IndicatorResult.fail);
    }
  }

  /// 执行请求的方法
  Future<List<ApplicationPo>> _request() async {
    return await LocalDb.instance.applicationDao.queryPagesByName(
      _search != '' ? _pageSize * 10 : _pageSize,
      _page * _pageSize,
      search: _search,
    );
  }

  @override
  void dispose() {
    _refreshController.dispose();
    super.dispose();
  }
}

final productModelProvider = StateNotifierProvider<HomeStateNotifier,
    ListViewState<List<ApplicationPo>>>(
  (ref) => HomeStateNotifier(
    api: ref.watch(apiService),
  ),
);
